/**
 * multi_mode_index.js - 热键检测系统启动入口
 * 支持多种模式: 多进程(cluster)、多线程(worker_threads)
 * 并支持TCP长连接与业务服务通信
 */
const ThreadsHotKeyDetector = require('./ThreadsHotKeyDetector');
const HotKeyApp = require('./HotKeyApp');
const { ConsolePusher, TcpPusher } = require('./Pusher');
const NettyServer = require('./NettyServer');
const ClientConnManager = require('./ClientConnManager');

/**
 * 创建并启动热键检测系统
 * @param {string} mode - 运行模式: 'single'(单线程), 'cluster'(多进程), 'threads'(多线程)
 */
function start(mode = 'single') {
  console.log(`启动热键检测系统，模式: ${mode}`);
  
  // 通用的规则配置
  const rules = [
    {
      appName: 'app1',
      keyType: 'string',
      interval: 10, // 10秒窗口
      threshold: 20 // 阈值为20
    },
    {
      appName: 'app2',
      keyType: 'hash',
      interval: 5, // 5秒窗口
      threshold: 10 // 阈值为10
    }
  ];
  
  // 根据模式启动不同的实现
  switch (mode) {
    case 'threads':
      startThreadsMode(rules);
      break;
    case 'cluster':
      startClusterMode(rules);
      break;
    case 'single':
    default:
      startSingleMode(rules);
      break;
  }
}

/**
 * 启动单线程模式
 * @param {Array} rules - 规则配置
 */
function startSingleMode(rules) {
  console.log('【单线程模式】启动中...');
  
  // 创建应用实例
  const app = new HotKeyApp();
  
  // 配置应用
  app.configure({
    useCluster: false, // 不使用多进程
    loggerOn: true,
    rules
  });
  
  // 启动应用
  app.start();
  
  console.log('【单线程模式】启动完成');
  console.log('系统已就绪，不会自动生成模拟数据');
  console.log('请使用test-client发送测试数据');
}

/**
 * 启动多进程模式 (cluster)
 * @param {Array} rules - 规则配置
 */
function startClusterMode(rules) {
  console.log('【多进程模式】启动中...');
  
  // 创建应用实例
  const app = new HotKeyApp();
  
  // 配置应用
  app.configure({
    useCluster: true, // 使用多进程
    workerCount: require('os').cpus().length, // 使用所有CPU核心
    loggerOn: true,
    rules
  });
  
  // 启动应用
  app.start();
  
  console.log('【多进程模式】启动完成');
}

/**
 * 启动多线程模式 (worker_threads)
 * @param {Array} rules - 规则配置
 */
function startThreadsMode(rules) {
  console.log('【多线程模式】启动中...');
  
  // 创建客户端连接管理器
  const clientManager = new ClientConnManager();
  
  // 创建多线程检测器
  const detector = new ThreadsHotKeyDetector();
  
  // 获取KeyRuleHolder单例并设置规则
  const KeyRuleHolder = require('./KeyRuleHolder');
  
  // 配置规则
  rules.forEach(rule => {
    KeyRuleHolder.setRule(rule.appName, rule.keyType, {
      interval: rule.interval,
      threshold: rule.threshold
    });
    console.log(`配置规则: 应用=${rule.appName}, 类型=${rule.keyType}, 窗口=${rule.interval}秒, 阈值=${rule.threshold}`);
  });
      
  // 创建长连接服务器，并设置键事件回调
  const nettyServer = new NettyServer({ 
    port: 11111, 
    clientManager,
    onKeyEvent: (hotKeyModel) => {
      // 将客户端发送的键事件传递给热键检测器
      detector.newKey(hotKeyModel, 'CLIENT');
    }
  });
  
  // 启动长连接服务器
  nettyServer.start()
    .then(() => {
      console.log('长连接服务器启动成功');
      
      // 创建TCP推送器
      const tcpPusher = new TcpPusher(clientManager);
      
      // 设置推送器（同时使用控制台和TCP推送）
      detector.setPushers([new ConsolePusher(), tcpPusher]);
      
      // 设置日志
      detector.setLoggerOn(true);
      
      // 设置日志采样率（每100次事件输出一次日志）
      detector.setLogSampleRate(100);
      
      // 设置日志时间间隔（同一个key在5秒内只输出一次日志）
      detector.setLogTimeInterval(5000);
      
      console.log('【多线程模式】启动完成');
      console.log('等待test-client连接并发送键事件...');
      console.log('系统已就绪，不会自动生成模拟数据');
      
      // 保存需要在退出时清理的资源
      const cleanupResources = {
        nettyServer,
        detector
      };
      
      // 添加更健壮的退出处理
      function gracefulShutdown(signal) {
        console.log(`收到 ${signal} 信号，正在关闭服务...`);
        
        // 清除模拟热键的定时器
        if (cleanupResources.simulationInterval) {
          clearInterval(cleanupResources.simulationInterval);
          console.log('已停止热键模拟');
        }
        
        // 设置强制退出的超时定时器（5秒后强制退出）
        const forceExitTimeout = setTimeout(() => {
          console.error('优雅退出超时，强制终止进程');
          process.exit(1);
        }, 5000);
        
        // 确保定时器不会阻止进程退出
        forceExitTimeout.unref();          // 停止服务
        nettyServer.stop()
          .then(() => {
            console.log('长连接服务器已停止');
            return detector.close();
          })
          .then(() => {
            console.log('热键检测器已关闭');
            clearTimeout(forceExitTimeout);
            console.log('服务已完全停止');
            process.exit(0);
          })
          .catch(err => {
            console.error('关闭服务时出错:', err);
            process.exit(1);
          });
      }
      
      // 监听多种退出信号
      process.on('SIGINT', () => gracefulShutdown('SIGINT')); // Ctrl+C
      process.on('SIGTERM', () => gracefulShutdown('SIGTERM')); // kill
      process.on('SIGHUP', () => gracefulShutdown('SIGHUP')); // 终端关闭
      
      // 打印客户端连接说明
      console.log('\n=== 客户端连接说明 ===');
      console.log('业务服务可通过TCP连接到端口11111');
      console.log('连接后发送注册消息：{ "type": "register", "appName": "your_app_name" }');
      console.log('随后将接收热键推送：{ "type": "hotkey", "data": { ... } }');
      console.log('======================\n');
    })
    .catch(err => {
      console.error('服务启动失败:', err);
      process.exit(1);
    });
}

/**
 * 空函数，用于替换原来的模拟热键函数
 * 不再自动模拟热键数据，仅依靠test-client发送的事件
 * @param {HotKeyApp} app - 应用实例
 */
function simulateHotKeys(app) {
  console.log('热键模拟功能已禁用，请使用test-client发送测试数据');
}

/**
 * 空函数，用于替换原来的模拟热键函数
 * 不再自动模拟热键数据，仅依靠test-client发送的事件
 * @param {ThreadsHotKeyDetector} detector - 多线程检测器
 * @returns {null} - 不再返回interval句柄
 */
function simulateHotKeysForThreads(detector) {
  console.log('热键模拟功能已禁用，请使用test-client发送测试数据');
  console.log('系统已准备就绪，等待test-client连接并发送键事件...');
  return null;
}

// 获取运行模式参数
const args = process.argv.slice(2);
const mode = args[0] || 'single';

// 启动应用
start(mode);
